/*!
 * \file Thread.h
 * \brief Thread class for Nude.
 * \author Nus
 * \date 2008/03/12, 00:11
 */

#ifndef __THREAD_H__
#define __THREAD_H__

#include "Types.h"
#include "Allocator.h"
#include "Mutex.h"

/*!
 * \class Thread
 * \brief Thread class based on POSIX thread.
 */
class Thread
{
public:
  //! \brief Default constructor.
  //! \param stack_size Stack size. Default stack size is 512KB (524288bytes).
  //! \param alloc Allocator. Pass NULL to use default allocator.
  Thread(u32 stack_size = 0x80000, Allocator* alloc = NULL);
  
  //! \brief Default destructor.
  virtual ~Thread();
  
  //! \brief Create thread.
  /*!
   * One you call this method, a thread will be automatically created.
   * If you want to create a thread, please derive this class & implement
   * thread in init(), term(), and run().
   */
  virtual s32 createThread(void);
  
  //! \brief Terminate thread.
  virtual s32 terminateThread(bool non_blocking = true);

  //! \brief Suspend thread.
  virtual s32 suspendThread(void);
  
  //! \brief Get state.
  s32 getState(void) const {
    return mState;
  }
  
  //! \brief Get POSIX thread handle.
  pthread_t* getThread(void) {
    return &mThread;
  }
  
  //! \brief Get POSIX thread attribute.
  pthread_attr_t* getThreadAttr(void) {
    return &mThreadAttr;
  }
  
  //! \brief Get stack size.
  u32 getStackSize(void) const {
    return mStackSize;
  }
  
  //! \brief Get mutex.
  Mutex* getMutex(void) const {
    return &mMutex;
  }

protected:
  void* mpStack;                  //!< Stack for thread.
  s32 mState;                     //!< State.
  u32 mStackSize;                 //!< Stack size.
  pthread_t mThread;              //!< POSIX thread handle.
  pthread_attr_t mThreadAttr;     //!< Thread attribute.
  Mutex mMutex;                   //!< Default mutex.
  bool mTerminated;               //!< Termination flag.

  //! \brief Initialization procedure.
  virtual void init(void);

  //! \brief Main loop.
  virtual void run(void);

  //! \brief Termination procedure.
  virtual void term(void);

  //! \brief Thread function.
  static void* threadFunc(void* user_param);

private:
  // None...

};

#endif
